#pragma once

#include "types.h"

typedef byte (*read_func_ptr)(word);
typedef void (*write_func_ptr)(word, byte);

class z80CPU 
{
public:    
    z80CPU();

	void user();

    void run(void);
    int exec(int cycles);
	void hook(read_func_ptr read_ptr, write_func_ptr write_ptr);

    void M1(void);
    void MREQ(void);
    void IORQ(void);
    void RD(void);
    void WR(void);
    void RFSH(void);
    
    void HALT(void);
    void WAIT(void);
    void INT(void);
    void NMI(void);
    void RESET(void);
    
    void BUSRQ(void);
    void BUSACK(void);
 
private:
	class z80Mem *mem;

	void setFile(std::string file);

	// Memory I/O function pointers
	byte (*read)(word);
	void (*write)(word, byte);

	////////////////////////////////////////
	//   Accumulator and Flag Registers   //
	////////////////////////////////////////

    pair(A, F, AF);
    pair(A, F, AFx);

	////////////////////////////////////////
	//      General-Purpose Registers     //
	////////////////////////////////////////

    pair(B, C, BC);
    pair(B, C, BCx);

    pair(D, E, DE);
    pair(D, E, DEx);

    pair(H, L, HL);
    pair(H, L, HLx);

	////////////////////////////////////////
	//      Special-Purpose Registers     //
	////////////////////////////////////////

	// Stack Pointer Register
    pair(S, P, SP);
    
	// Program Counter Register
	pair(P, C, PC);

	// Index Registers
    word IX, IY;
    
	// Interrupt Page Address Register, Memory Refresh Register
	byte I, R;              
    
	// Instruction Register
	byte IR;                
	
	// Interrupt Enable Flip-Flop	
	byte IFF;	
	
	// IFF is set or reset by the programmer using the Enable Interrupt (EI) and Disable Interrupt (DI) 
	// instructions. When the IFF is reset, an interrupt cannot be accepted by the CPU.

	// HALT state
	byte halt;
};
